/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package runebound.basedatos;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import runebound.combate.FaseCombate;
import runebound.factorias.MonstruoFactoria;
import runebound.modelo.Ciudad;
import runebound.modelo.Gema;
import runebound.modelo.Mazo;
import runebound.modelo.TipoAmenaza;
import runebound.modelo.heores.experiencia.Atributo;
import runebound.modelo.heores.items.ItemPasiva;
import runebound.modelo.heores.items.Item;
import runebound.modelo.heores.items.ItemActivaAtaque;
import runebound.modelo.heores.items.ItemActivaPasivaActivable;
import runebound.modelo.heores.items.ItemActivoCancelacionDevolucionHeridas;
import runebound.modelo.heores.items.ItemActivoCancelacionHerida;
import runebound.modelo.heores.items.ItemActivoMejoraAtaqueConExito;
import runebound.modelo.heores.items.ModoEmpleoItem;
import runebound.modelo.heores.items.TipoItem;
import runebound.modelo.monstruos.Monstruo;
import runebound.ui.mapa.Terreno;
import runebound.ui.mapa.TileMapa;

/**
 *
 * @author malopez
 */
public class RBConexion {
    
    private Connection connection;
    private static RBConexion instance;
    private RBConexion() throws ClassNotFoundException, SQLException {
        Class.forName("org.sqlite.JDBC");
        connection = DriverManager.getConnection("jdbc:sqlite:./libs/database.db");
    }

    public static RBConexion getInstance() {
        synchronized(RBConexion.class){
            if(instance==null){
                try {
                    instance = new RBConexion();
                } catch (ClassNotFoundException ex) {
                    Logger.getLogger(RBConexion.class.getName()).log(Level.SEVERE, null, ex);
                    System.exit(1);
                } catch (SQLException ex) {
                    Logger.getLogger(RBConexion.class.getName()).log(Level.SEVERE, null, ex);
                    System.exit(1);
                }
            }
        }
        return instance;
    }
    
    public Monstruo getMonstruo(int id){
        try {
            Statement statement = connection.createStatement();
            statement.setQueryTimeout(30);
            ResultSet resultSet =  statement.executeQuery("select * from Monstruo where id="+id+";");
            
            return MonstruoFactoria.getInstance().createMonstruo(resultSet);
        } catch (SQLException ex) {
            Logger.getLogger(RBConexion.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }
    
    public List<Monstruo> allMonstruo(){
        List<Monstruo> monstruos = new ArrayList<>();
        try{
            Statement statement = connection.createStatement();
            statement.setQueryTimeout(30);
            ResultSet resultSet =  statement.executeQuery("select * from Monstruo;");
            while(resultSet.next()){
                monstruos.add(MonstruoFactoria.getInstance().createMonstruo(resultSet));
            }
            return monstruos;
        }catch (SQLException ex) {
            Logger.getLogger(RBConexion.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }
    
    public TileMapa getTile(int i, int j){
        try{
            Statement statement = connection.createStatement();
            statement.setQueryTimeout(30);
            ResultSet resultSet =  statement.executeQuery("select * from Terreno where i="+i+" and j="+j+";");
            TileMapa tile = new TileMapa(Terreno.valueOf(resultSet.getString("tipoTerreno")), i, j);
            return tile;
        }catch (SQLException ex) {
            Logger.getLogger(RBConexion.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }
    
    public List<Rio> getRios(){
        try{
            Statement statement = connection.createStatement();
            statement.setQueryTimeout(30);
            ResultSet resultSet =  statement.executeQuery("select * from Rio");
            List<Rio> rios = new ArrayList<>();
            while(resultSet.next()){
                Rio rio = new Rio(FronteraConexion.valueOf(resultSet.getString("entrada")),
                        FronteraConexion.valueOf(resultSet.getString("salida")),
                        resultSet.getInt("i"), 
                        resultSet.getInt("j"));
                rios.add(rio);
            }
            return rios;
        }catch (SQLException ex) {
            Logger.getLogger(RBConexion.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }
    
    
    public List<Camino> getCaminos(){
        try{
            Statement statement = connection.createStatement();
            statement.setQueryTimeout(30);
            ResultSet resultSet =  statement.executeQuery("select * from Camino");
            List<Camino> caminos = new ArrayList<>();
            while(resultSet.next()){
                Camino camino = new Camino(FronteraConexion.valueOf(resultSet.getString("entrada")),
                        FronteraConexion.valueOf(resultSet.getString("salida")),
                           resultSet.getInt("i"), 
                           resultSet.getInt("j")
                        );
                caminos.add(camino);
            }
            return caminos;
        }catch (SQLException ex) {
            Logger.getLogger(RBConexion.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }
    
    
    public List<Gema> getGemas(){
        try{
            Statement statement = connection.createStatement();
            statement.setQueryTimeout(30);
            ResultSet resultSet =  statement.executeQuery("select * from Gema");
            List<Gema> gemas = new ArrayList<Gema>();
            while(resultSet.next()){
                Gema gema = new Gema(resultSet.getInt("i"), 
                                     resultSet.getInt("j"),
                                     TipoAmenaza.valueOf(resultSet.getString("tipoAmenaza")),
                        resultSet.getString("sol").equalsIgnoreCase("SI"));
                gemas.add(gema);
            }
            return gemas;
        }catch (SQLException ex) {
            Logger.getLogger(RBConexion.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }
    
    
    
    public List<Ciudad> getCiudades(){
        try{
            Statement statement = connection.createStatement();
            statement.setQueryTimeout(30);
            ResultSet resultSet =  statement.executeQuery("select * from Ciudad");
            List<Ciudad> ciudades = new ArrayList<Ciudad>();
            while(resultSet.next()){
                Ciudad ciudad = new Ciudad(resultSet.getInt("i"), 
                                            resultSet.getInt("j"),
                                            resultSet.getString("titulo"));
                ciudades.add(ciudad);
            }
            return ciudades;
        }catch (SQLException ex) {
            Logger.getLogger(RBConexion.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }
    
    
    /**
     * busca todos los items pasivos y genera las cartas adecuadas en función
     * del número que debería haber de ellos
     * @return 
     */
    public List<Item> allItemsPasivos(){
        List<Item> items = new ArrayList<>();
        try{
            Statement statement = connection.createStatement();
            statement.setQueryTimeout(30);
            ResultSet resultSet =  statement.executeQuery("select * from ItemPasiva");
            while(resultSet.next()){
                int ncartas = resultSet.getInt("numeroCartas");
                String modificador = resultSet.getString("modificador");
                    String[] modificadorSplit = modificador.split("_");
                    Atributo atributo = Atributo.valueOf(modificadorSplit[0]);
                    int valor = Integer.parseInt(modificadorSplit[1]);
                for(int i = 0;i<ncartas;i++){
                    
                    ItemPasiva arma = new ItemPasiva(resultSet.getString("titulo"),
                            resultSet.getString("descripcionAyuda"),
                            resultSet.getInt("oro"), 
                            TipoItem.valueOf(resultSet.getString("tipo")),
                            ModoEmpleoItem.valueOf(resultSet.getString("empleo")), 
                            atributo,
                            valor);
                    items.add(arma);
                }
            }
        }catch(SQLException ex) {
            Logger.getLogger(RBConexion.class.getName()).log(Level.SEVERE, null, ex);
        }
        return items;
    }
    
    /**
     * Busca todos los items de tipo Armas Activas Ataque
     * @return 
     */
    public List<Item> allItemsActivasAtaque(){
        List<Item> items = new ArrayList<>();
        try{
            Statement statement = connection.createStatement();
            statement.setQueryTimeout(30);
            ResultSet resultSet =  statement.executeQuery("select * from ItemActivaAtaque");
            while(resultSet.next()){
                int ncartas = resultSet.getInt("numeroCartas");
                int oro = resultSet.getInt("oro");
                String descripcionAyuda = resultSet.getString("descripcionAyuda");
                String titulo = resultSet.getString("titulo");
                TipoItem tipo = TipoItem.valueOf(resultSet.getString("tipo"));
                ModoEmpleoItem modoEmpleoItem = ModoEmpleoItem.valueOf(resultSet.getString("empleo"));
                for(int i = 0;i<ncartas;i++){
                    Item arma=null;
                    String coste = resultSet.getString("coste");
                    Atributo costeAtributo = Atributo.VIDA;
                    int costeAtributoValor=0;
                    if(!coste.equalsIgnoreCase("NADA")){
                        costeAtributo = Atributo.valueOf(coste.split("_")[0]);
                        costeAtributoValor = Integer.parseInt(coste.split("_")[1]);
                    }
                    
                    arma = new ItemActivaAtaque(FaseCombate.valueOf(resultSet.getString("tipoAtaque")), 
                            resultSet.getInt("heridas"),
                            costeAtributo,costeAtributoValor ,
                            oro, 
                            tipo, 
                            modoEmpleoItem,
                            titulo, 
                            descripcionAyuda);
                    
                    items.add(arma);
                }
            }
        }catch(SQLException ex) {
            Logger.getLogger(RBConexion.class.getName()).log(Level.SEVERE, null, ex);
        }
        return items;
    }
    
    /**
     * 
     * @return 
     */
    public List<Item> allItemsCancelarHeridas(){
        List<Item> items = new ArrayList<>();
        try{
            Statement statement = connection.createStatement();
            statement.setQueryTimeout(30);
            ResultSet resultSet =  statement.executeQuery("select * from ItemActivaCancelacionHeridas");
            while(resultSet.next()){
                int ncartas = resultSet.getInt("numeroCartas");
                int oro = resultSet.getInt("oro");
                String descripcionAyuda = resultSet.getString("descripcionAyuda");
                String titulo = resultSet.getString("titulo");
                TipoItem tipo = TipoItem.valueOf(resultSet.getString("tipo"));
                ModoEmpleoItem modoEmpleoItem = ModoEmpleoItem.valueOf(resultSet.getString("empleo"));
                for(int i = 0;i<ncartas;i++){
                    Item arma=null;
                    arma = new ItemActivoCancelacionHerida(
                            resultSet.getInt("heridasCanceladas"),
                            oro,
                            tipo,
                            modoEmpleoItem,
                            titulo, 
                            descripcionAyuda);
                    
                    items.add(arma);
                }
            }
        }catch(SQLException ex) {
            Logger.getLogger(RBConexion.class.getName()).log(Level.SEVERE, null, ex);
        }
        return items;
    }
    
    /**
     * 
     * @return 
     */
    public List<Item> allItemsCancelarDevolverHeridas(){
        List<Item> items = new ArrayList<>();
        try{
            Statement statement = connection.createStatement();
            statement.setQueryTimeout(30);
            ResultSet resultSet =  statement.executeQuery("select * from ItemActivaDevolucionHeridas");
            while(resultSet.next()){
                int ncartas = resultSet.getInt("numeroCartas");
                int oro = resultSet.getInt("oro");
                String descripcionAyuda = resultSet.getString("descripcionAyuda");
                String titulo = resultSet.getString("titulo");
                TipoItem tipo = TipoItem.valueOf(resultSet.getString("tipo"));
                ModoEmpleoItem modoEmpleoItem = ModoEmpleoItem.valueOf(resultSet.getString("empleo"));
                for(int i = 0;i<ncartas;i++){
                    Item arma=null;
                    arma = new ItemActivoCancelacionDevolucionHeridas(
                            resultSet.getInt("heridasCanceladas"),
                            resultSet.getInt("heridasDevueltas"), 
                            oro, 
                            tipo, 
                            modoEmpleoItem,
                            titulo, 
                            descripcionAyuda);
                    
                    items.add(arma);
                }
            }
        }catch(SQLException ex) {
            Logger.getLogger(RBConexion.class.getName()).log(Level.SEVERE, null, ex);
        }
        return items;
    }
    
    
    /**
     * 
     * @return 
     */
    public List<Item> allItemsActivaMejoraAtaqueExitoso(){
        List<Item> items = new ArrayList<>();
        try{
            Statement statement = connection.createStatement();
            statement.setQueryTimeout(30);
            ResultSet resultSet =  statement.executeQuery("select * from ItemActivaMejoraAtaqueExitoso");
            while(resultSet.next()){
                int ncartas = resultSet.getInt("numeroCartas");
                int oro = resultSet.getInt("oro");
                String descripcionAyuda = resultSet.getString("descripcionAyuda");
                String titulo = resultSet.getString("titulo");
                TipoItem tipo = TipoItem.valueOf(resultSet.getString("tipo"));
                ModoEmpleoItem modoEmpleoItem = ModoEmpleoItem.valueOf(resultSet.getString("empleo"));
                for(int i = 0;i<ncartas;i++){
                    Item arma=null;
                    FaseCombate faseCombate = FaseCombate.valueOf(resultSet.getString("tipoAtaque"));
                    int heridas = resultSet.getInt("heridasMejorada");
                    arma = new ItemActivoMejoraAtaqueConExito(faseCombate,
                            heridas, 
                            oro, 
                            tipo, 
                            modoEmpleoItem, 
                            titulo, 
                            descripcionAyuda);
                    
                    items.add(arma);
                }
            }
        }catch(SQLException ex) {
            Logger.getLogger(RBConexion.class.getName()).log(Level.SEVERE, null, ex);
        }
        return items;
    }
    
    /**
     * 
     * @return 
     */
    public List<Item> allItemsActivaPasivaActivable(){
        List<Item> items = new ArrayList<>();
        try{
            Statement statement = connection.createStatement();
            statement.setQueryTimeout(30);
            ResultSet resultSet =  statement.executeQuery("select * from ItemActivaPasivaActivable");
            while(resultSet.next()){
                int ncartas = resultSet.getInt("numeroCartas");
                int oro = resultSet.getInt("oro");
                String descripcionAyuda = resultSet.getString("descripcionAyuda");
                String titulo = resultSet.getString("titulo");
                TipoItem tipo = TipoItem.valueOf(resultSet.getString("tipo"));
                ModoEmpleoItem modoEmpleoItem = ModoEmpleoItem.valueOf(resultSet.getString("empleo"));
                for(int i = 0;i<ncartas;i++){
                    Item arma=null;
                    String modificador = resultSet.getString("modificador");
                    arma = new ItemActivaPasivaActivable(modificador, 
                            oro, 
                            tipo,
                            modoEmpleoItem, 
                            titulo, 
                            descripcionAyuda);
                    items.add(arma);
                }
            }
        }catch(SQLException ex) {
            Logger.getLogger(RBConexion.class.getName()).log(Level.SEVERE, null, ex);
        }
        return items;
    }
    
    

    /**
     * Obtiene todos los items validos en el mercado
     *  
     * @return 
     */
    public Mazo<Item> allItems() {
        List<Item> items = new ArrayList();
        items.addAll(this.allItemsPasivos());
        items.addAll(this.allItemsActivaMejoraAtaqueExitoso());
        items.addAll(this.allItemsActivasAtaque());
        items.addAll(this.allItemsCancelarDevolverHeridas());
        items.addAll(this.allItemsCancelarHeridas());
        items.addAll(this.allItemsActivaPasivaActivable());
        return new Mazo<Item>(items);   
    }
}
